/*----------------------------------------------------------------------------------------
*
*  Copyright 2019, Gao Hai Hui, <fromzeropoint@126.com>.  All rights reserved.
*  https://gitee.com/helloworldghh/xoskit.git
*  Use of this source code is governed by a MIT license
*  that can be found in the License file.
*
----------------------------------------------------------------------------------------*/
#include "../import/head.h"
#include "../data_struct/head.h"
#include "json_impl.h"
#include "hook.h"
#include "mgr.h"

////////////////////////////////////////////////////////////////////////////////////////////
// 

namespace xos_json
{

    //////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    static xos_container::i_container* container_ptr = 0;
    static mgr* mgr_ptr = 0;

    //////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    mgr::mgr()
    {
    }

    mgr::~mgr()
    {
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    int mgr::static_init( xos_container::i_container* pContainer, i_json_mgr** ppv )
    {
        return xos_stl::static_init_module( pContainer, ppv, container_ptr, mgr_ptr );
    }

    xos_container::i_container* mgr::container()
    {
        return container_ptr;
    }

    mgr* mgr::get()
    {
        return mgr_ptr;
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    // 
    // xos_box::i_str_property -> i_json
    // 

    int mgr::prop_to_json( xos_box::i_str_property * pProperty, char * lpszJson, int nSize, int * pnLenRet )
    {
        int ret = 0;

        i_json * pJson = 0;

        if( 0 == ret )
        {
            ret = prop_to_json( pProperty, &pJson );
        }

        if( 0 == ret )
        {
            ret = pack( pJson, lpszJson, nSize, pnLenRet );
        }

        xos_stl::release_interface( pJson );

        return ret;
    }

    int mgr::prop_to_json( xos_box::i_str_property * pProperty, i_json ** ppv )
    {
        int ret = 0;

        i_json * pJson = 0;

        if( 0 == ret )
        {
            pJson = mgr::get()->json();
        }

        if( 0 == ret )
        {
            ret = prop_to_json( pProperty, pJson );
        }

        if( ( 0 == ret ) && ppv )
        {
            *ppv = pJson;
            pJson = 0;
        }

        xos_stl::release_interface( pJson );

        return ret;
    }

    // 
    // pack to string
    // 
    int mgr::pack( i_json * pv, char * lpszStr, int nLen, int * pnLenRet )
    {
        int nRet = 0;

        json_impl * pJson = ( json_impl * )pv;
        std::string str;

        if( 0 == nRet )
        {
            Json::FastWriter writer;
            str = writer.write( pJson->m_value );
        }

        if( ( 0 == nRet ) && ( (int)str.length() >= nLen ) )
        {
            nRet = 1;
        }

        if( ( 0 == nRet ) && lpszStr )
        {
            mgr::container()->crt()->strcpy( lpszStr, nLen, str.c_str() );
        }

        if(pnLenRet )
        {
            *pnLenRet = ( int )str.length();
        }

        return nRet;
    }

    // 
    // parse
    // 
    int mgr::parse( const char * lpszStr, int nLen, i_json ** ppv )
    {
        int nRet = 0;

        json_impl * pJson = 0;

        if( 0 == nRet )
        {
            pJson = json_impl::get_item_from_pool();
            pJson->init();
        }

        if( 0 == nRet )
        {
            Json::Reader reader;
            bool bRet = reader.parse( lpszStr, lpszStr + nLen, pJson->m_value, false );
            if( !bRet )
            {
                nRet = 1;
            }
        }

        if( 0 == nRet )
        {
            *ppv = ( i_json * )pJson;
            pJson = 0;
        }

        if( pJson )
        {
            pJson->release();
            pJson = 0;
        }

        return nRet;
    }

    // 
    // create node
    // 
    i_json * mgr::json()
    {
        json_impl::T * p = 0;
        xos_stl::init_pool_item( p );
        return p;
    }

    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    int mgr::prop_to_json( xos_box::i_str_property * pProperty, i_json * pRoot )
    {
        int ret = 0;

        xos_box::i_variant * pVT = 0;
        const char * lpszKey = 0;

        for( pProperty->reset(); ( pVT = pProperty->next( &lpszKey, 0, 0, 0 ) ); )
        {
            xos_box::i_variant::VT_TYPE vType = pVT->get_type( 0 );
            switch( vType )
            {
            case xos_box::i_variant::VT_STRING:
                {
                    pRoot->set_str( lpszKey, pVT->str() );
                }
                break;
            case xos_box::i_variant::VT_DOUBLE:
                {
                    pRoot->set_double( lpszKey, pVT->dbl() );
                }
                break;
            case xos_box::i_variant::VT_FLOAT:
                {
                    pRoot->set_double( lpszKey, pVT->flt() );
                }
                break;
            case xos_box::i_variant::VT_I32:
                {
                    pRoot->set_int( lpszKey, pVT->i32() );
                }
                break;
            case xos_box::i_variant::VT_OBJECT:
                {
                    obj_to_json( lpszKey, pVT, pRoot );
                }
                break;
            default:
                {
                    pRoot->set_str( lpszKey, "unknown" );
                }
                break;
            }
        }

        return ret;
    }

    int mgr::obj_to_json( const char * lpszKey, xos_box::i_variant * pVT, i_json * pRoot )
    {
        int result = 0;
        int ret = 0;

        if( ( 0 == ret ) && !pVT )
        {
            ret = 1;
        }

        if( 0 == ret )
        {
            xos_box::i_str_property * pProperty = pVT->str_prop( 0 );
            if( pProperty )
            {
                helper_prop_to_json( lpszKey, pProperty, pRoot );
                ret = 1;
            }
        }

        if( 0 == ret )
        {
            xos_box::i_list * pList = pVT->list( 0 );
            if( pList )
            {
                helper_list_to_json( lpszKey, pList, pRoot );
                ret = 1;
            }
        }

        return result;
    }

    int mgr::helper_prop_to_json( const char * lpszKey, xos_box::i_str_property * pProperty, i_json * pRoot )
    {
        int ret = 0;

        i_json * pJson = 0;

        if( 0 == ret )
        {
            pJson = mgr::get()->json();
        }

        if( 0 == ret )
        {
            prop_to_json( pProperty, pJson );
        }

        if( 0 == ret )
        {
            pRoot->set_json( lpszKey, pJson );
        }

        xos_stl::release_interface( pJson );

        return ret;
    }

    int mgr::helper_list_to_json( const char * lpszKey, xos_box::i_list * pList, i_json * pRoot )
    {
        int ret = 0;

        xos_box::i_variant * pVT = 0;
        i_json * pJson = 0;

        if( 0 == ret )
        {
            pJson = mgr::get()->json();
        }

        for( pList->reset(); ( 0 == ret ) && ( pVT = (xos_box::i_variant *)pList->next() ); )
        {
            xos_box::i_variant::VT_TYPE vType = pVT->get_type( 0 );
            switch( vType )
            {
            case xos_box::i_variant::VT_STRING:
                {
                    pJson->append_str( pVT->str() );
                }
                break;
            case xos_box::i_variant::VT_DOUBLE:
                {
                    pJson->append_double( pVT->dbl() );
                }
                break;
            case xos_box::i_variant::VT_FLOAT:
                {
                    pJson->append_double( pVT->flt() );
                }
                break;
            case xos_box::i_variant::VT_I32:
                {
                    pJson->append_int( pVT->i32() );
                }
                break;
            case xos_box::i_variant::VT_OBJECT:
                {
                    obj_to_json( lpszKey, pVT, pJson );
                }
                break;
            default:
                {
                    pJson->append_str( "unknown" );
                }
                break;
            }
        }

        if( 0 == ret )
        {
            pRoot->set_json( lpszKey, pJson );
        }

        xos_stl::release_interface( pJson );

        return ret;
    }

    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    int mgr::put_back_to_pool()
    {
        int ret = 0;
        delete this;
        return ret;
    }

    int mgr::init()
    {
        int ret = 0;

        if( 0 == ret )
        {
            ret = hook::init();
        }

        return ret;
    }

    int mgr::term()
    {
        int ret = 0;
        hook::term();
        return ret;
    }

} // xos_json
